<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- 
    new Vue 得到实例对象，称为 根实例，组件叫 根组件

    生命周期
      概念：组件从创建到销毁（卸载）的过程，就叫做一个生命周期。
    
    生命周期钩子函数
      概念：在一个生命周期过程中，特定的时机会主动触发的函数，就称为生命周期的钩子函数。
      主要有八个（后续会增加两个keep-alive）
        创建阶段
          1. beforeCreate     创建前
          2. created          创建完成
        挂载阶段
          3. beforeMount      挂载前
          4. mounted          挂载完成
        更新阶段
          5. beforeUpdate     更新前
          6. updated          更新完成
        销毁/卸载阶段
          7. beforeDestroy  || beforeUnmount      销毁/卸载 前
          8. destroyed      || unmounted          销毁/卸载 完成
   -->

    <div id="app">
      <h1>学习生命周期</h1>
      <p>{{ msg }}</p>

      <div style="height: 2000px"></div>
    </div>

    <button onclick="vm.$mount('#app')">点我，挂载</button>

    <script src="../lib/vue.js"></script>
    <script>
      const vm = new Vue({
        // 模板
        //    有 template 选项的时候，会基于 template 的内容发来生成虚拟DOM，替换到挂载点元素
        //    没有 template 选项的时候，会将 挂载点元素整个作为 template 的内容来生成虚拟DOM，替换到挂载点元素
        // template: `
        //   <p>Hello</p>
        // `,
        data: {
          msg: "hello",
        },
        methods: {
          fn1() {},

          handleScroll() {
            console.log("scroll");
          },
        },
        beforeCreate() {
          // PS: 不能获取数据、方法之类
          console.log("beforeCreate", this.msg, this.fn1);
        },
        created() {
          // PS: 数据代理，事件绑定都已经完成了，这时可以通过 this 获取到数据、方法
          // 应用场景：
          //    1. 调用接口
          console.log("created", this.msg, this.fn1);
        },
        beforeMount() {
          // PS: 这时还无法获取到需要的真实DOM对象
          console.log("beforeMount", document.querySelector("p").innerHTML); // {{ msg }}
        },
        mounted() {
          // PS: 将虚拟DOM渲染到真实DOM上了，这时可以获取的想要的真实DOM对象
          // 应用场景：
          //    1. 调用接口
          //    2. 操作真实DOM
          //    3. 绑定全局的一些事件，addEventListener('scroll')
          //    4. 做事件订阅
          //    5. setTimeout / setInterval
          console.log("mounted", document.querySelector("p").innerHTML);

          window.addEventListener("scroll", this.handleScroll);
        },
        beforeUpdate() {
          // PS: 数据修改了，Vue内部重新生成虚拟DOM，还未更新到真实DOM上时触发
          console.log("beforeUpdate", document.querySelector("p").innerHTML);
        },
        updated() {
          // PS: 数据更新且真实DOM也重新渲染之后，触发
          //      不要在这儿修改数据，调用接口，一定要玩的时候，需要加上条件控制。
          console.log("updated", document.querySelector("p").innerHTML);
        },
        beforeDestroy() {
          // 使用场景：
          //    1. 做收尾工作，clearInterval, removeEventListener, 取消事件的订阅
          console.log("beforeDestroy");

          window.removeEventListener("scroll", this.handleScroll);
        },
        destroyed() {
          // PS: 响应式数据取消代理，事件被移除。也就是说修改数据，不会再引起页面的更新。
          console.log("destroyed");
        },
      });
    </script>
  </body>
</html>
